<script setup lang="ts">
  import { ElDivider, FormInstance, UploadFile, UploadRawFile } from 'element-plus'
  import { computed, h, ref, watch } from 'vue'
  import defaultUploadImg from '@/assets/image/avatar_upload_default.png'
  import { deleteFile, knowledgeAnnexUpload } from '@/api/upload'
  import infoTip from '@/config/info-tip'
  import { HMessageBox, HMessage } from '@/components/common/message'
  import { useGetFaultTypes, useGetFaultDetail } from '@/services/pages/know/fault'
  import useGetGoodTypeOptions from '@/services/pages/common/good-type-options'
  import { useFaultCreate } from '@/services/pages/know/useFault'

  const { form, createLoading, create, resetForm } = useFaultCreate()
  const { goodTypeOptions, getGoodTypeOptionsLoading, getGoodTypeOptions } = useGetGoodTypeOptions()
  const { faultTypes, getFaultTypesLoading, getFaultTypes } = useGetFaultTypes()
  const { faultDetail, getFaultDetailLoading, getFaultDetail } = useGetFaultDetail()

  defineOptions({
    name: 'FaultCreateModal',
  })

  const props = defineProps({
    faultId: {
      type: String,
      default: () => '',
    },
  })

  const emits = defineEmits<{
    (e: 'search'): void
  }>()

  // 间距组件的间隔符
  const spacer = h(ElDivider, {
    direction: 'vertical',
    style: 'display: flex; align-items: center;',
  })

  // 抽屉显示状态
  const visible = defineModel('visible', { type: Boolean, default: false })

  // 表单组件实例
  const formInstance = ref<FormInstance | null>(null)

  // 表单验证规则
  const faultRules = ref({
    oneFaultTypeId: [{ required: true, message: '请选择处理类型', trigger: ['change', 'blur'] }],
    name: [{ required: true, message: '请输入分类', trigger: ['change', 'blur'] }],
    goodType: [{ required: true, message: '请选择商品分类', trigger: ['change', 'blur'] }],
    faultType: [{ required: true, message: '请选择处理类型', trigger: ['change', 'blur'] }],
    visibilityType: [{ required: true, message: '请选择可见类型', trigger: ['change', 'blur'] }],
  })

  // 故障图片
  const faultImg = ref<Array<{ file: UploadFile; imgUrl: string; index: number }>>([])

  // 解决图片
  const solveImg = ref<Array<{ file: UploadFile; imgUrl: string; index: number }>>([])

  // 要删除的图片url集合
  const deleteImgUrls = ref<Array<string>>([])

  // 上传图片加载
  const uploadImgLoading = ref(false)

  // 商品分类id选择列表
  const selectedGoodTypeIds = ref<Array<string>>([])

  // 获取所有的二级商品分类id
  const getAllSecondGoodType = computed(() => {
    const result: Array<GoodTypeOptions> = []
    goodTypeOptions.value.forEach((goodType) => {
      result.push(...goodType.childData)
    })
    return result
  })

  /**
   * 文件转化为临时预览路径
   * @param {UploadRawFile} file - 文件对象
   */
  const fileRawToTempUrl = (file: UploadRawFile) => {
    return URL.createObjectURL(file)
  }

  /**
   * 图片上传验证
   * @param {UploadRawFile} file - 文件对象
   * @param {('fault'|'solve')} type - 上传类型
   */
  const imgUploadValidate = (file: UploadRawFile, type: 'fault' | 'solve') => {
    if (!file.type.includes('image')) {
      return infoTip.know.fault.list.fileType
    }

    if (file.size / 1024 / 1024 > 50) {
      return infoTip.know.fault.list.pictureSize
    }

    if (type === 'fault' && faultImg.value.length >= 10) {
      return infoTip.know.fault.list.pictureQuantity
    }

    if (type === 'solve' && solveImg.value.length >= 10) {
      return infoTip.know.fault.list.pictureQuantity
    }

    return ''
  }

  /**
   * 获取图片数组引用
   * @param {('fault'|'solve')} type - 图片类型
   */
  const getImgArr = (type: 'fault' | 'solve') => {
    return type === 'fault' ? faultImg : solveImg
  }

  /**
   * 上传图片
   * @param {Object} file - 文件对象
   * @param {(fault|resolve)} type - 上传类型：fault-故障图、solve-解决图
   */
  const handleUploadImg = (file: UploadFile, type: 'fault' | 'solve') => {
    const errMsg = imgUploadValidate(file.raw, type)
    if (errMsg) {
      HMessageBox.error(errMsg)
      return
    }

    const _imgList = getImgArr(type)
    _imgList.value.push({
      file,
      imgUrl: fileRawToTempUrl(file.raw),
      index: _imgList.value.length,
    })
  }

  /**
   * 移除图片
   * @param {Object} file - 文件对象
   * @param {('fault'|'solve')} type - 移除类型
   */
  const handleRemoveImg = (
    file: { file?: UploadFile; imgUrl: string; index: number },
    type: 'fault' | 'solve',
  ) => {
    const imgList = getImgArr(type)
    imgList.value = imgList.value.filter((o) => file.index !== o.index)
    deleteImgUrls.value.push(file.imgUrl)
  }

  /**
   * 文件上传
   * @param {('fault'|'solve')} type - 文件类型
   */
  const imgUpload = async (type: 'fault' | 'solve') => {
    const imgList = getImgArr(type)
    if (imgList.value.every((item) => !!item.file)) {
      const files = imgList.value.map((item) => item.file.raw)
      if (files.length > 0) {
        uploadImgLoading.value = true
        const res = await knowledgeAnnexUpload(files)
        imgList.value = imgList.value.filter((item) => !item.file)
        res.data.data.rows.forEach((item) => {
          imgList.value.push({
            index: imgList.value.length,
            imgUrl: item,
            file: null,
          })
        })
        uploadImgLoading.value = false
      }
    }
  }

  /**
   * 文件删除
   */
  const imgDel = async () => {
    if (deleteImgUrls.value.length !== 0) {
      await deleteFile(deleteImgUrls.value)
    }
  }

  /**
   * 保存事件
   */
  const onSave = async () => {
    if (!formInstance.value) {
      return
    }

    try {
      await formInstance.value.validate()
      await imgUpload('fault')
      await imgUpload('solve')
      form.value.faultImages = faultImg.value.map((item) => {
        return {
          path: item.imgUrl,
        }
      })
      form.value.solutionImages = solveImg.value.map((item) => {
        return {
          path: item.imgUrl,
        }
      })
      await imgDel()
      form.value.goodsTypeVos = []
      selectedGoodTypeIds.value.forEach((goodTypeId) => {
        const firstGoodType = goodTypeOptions.value.find((goodTypeOption) => {
          return goodTypeOption.childData.map((item) => item.id).includes(goodTypeId)
        })

        const firstGoodTypeIds = form.value.goodsTypeVos.map((item) => item.goodsOneTypeId)
        const secondGoodTypeIds = form.value.goodsTypeVos.map((item) => item.goodsTwoTypeId)

        if (
          firstGoodType &&
          (!firstGoodTypeIds.includes(firstGoodType.id) || !secondGoodTypeIds.includes(goodTypeId))
        ) {
          form.value.goodsTypeVos.push({
            goodsOneTypeId: firstGoodType.id,
            goodsTwoTypeId: goodTypeId,
            goodsThreeTypeId: '',
          })
        }
      })
      const res = await create()
      if (res.code === 20000) {
        HMessage.success(
          props.faultId
            ? infoTip.know.fault.list.updateSuccess
            : infoTip.know.fault.list.addSuccess,
        )
        visible.value = false
        resetForm()
        emits('search')
        return
      }

      HMessageBox.error(infoTip.know.fault.list[res.code] || res.message)
    } catch (error) {
      // 校验失败
    }
  }

  /**
   * 清空所有的信息
   */
  const clearInfo = () => {
    faultImg.value.length = 0
    solveImg.value.length = 0
    resetForm()
  }

  /**
   * 回显选择的商品分类
   */
  const echoGoodType = () => {
    const { goodsTypeVos } = faultDetail.value
    selectedGoodTypeIds.value = goodsTypeVos.map((item) => item.goodsTwoTypeId)
  }

  /**
   * 回显故障图片
   */
  const echoFaultImg = () => {
    faultDetail.value.faultImages.forEach((img, index) => {
      faultImg.value.push({
        index,
        imgUrl: img.path,
        file: null,
      })
    })
  }

  /**
   * 回显解决图片
   */
  const echoSolveImg = () => {
    faultDetail.value.solutionImages.forEach((img, index) => {
      solveImg.value.push({
        index,
        imgUrl: img.path,
        file: null,
      })
    })
  }

  /**
   * 回显内容
   */
  const echoInfo = async () => {
    await getFaultDetail(props.faultId)
    clearInfo()
    form.value = faultDetail.value
    echoGoodType()
    echoFaultImg()
    echoSolveImg()
  }

  /**
   * 初始化
   */
  const init = () => {
    selectedGoodTypeIds.value.length = 0
    getGoodTypeOptions()
    getFaultTypes()
    clearInfo()
  }

  /**
   * 详情添加事件
   */
  const onReasonAdd = () => {
    form.value.faultReasons.push({
      id: '',
      content: '',
    })
  }

  /**
   * 详情删除事件
   * @param {Number} index - 原因索引
   */
  const onReasonDel = (index: number) => {
    const reasons = form.value.faultReasons.splice(index, 1)
    if (reasons[0] && reasons[0].id) {
      form.value.delFaultReasonIds.push(reasons[0].id)
    }
  }

  /**
   * 解决措施添加事件
   */
  const onSolveAdd = () => {
    form.value.solutions.push({
      id: '',
      content: '',
    })
  }

  /**
   * 解决措施删除事件
   * @param {Number} index - 原因索引
   */
  const onSolveDel = (index: number) => {
    const solves = form.value.solutions.splice(index, 1)
    if (solves[0] && solves[0].id) {
      form.value.delSolutionIds.push(solves[0].id)
    }
  }

  /**
   * 隐藏抽屉
   */
  const hideDrawer = () => {
    visible.value = false
    clearInfo()
  }

  watch(
    visible,
    async (value) => {
      if (value) {
        init()
        if (props.faultId) {
          echoInfo()
        }
      }
    },
    { immediate: true },
  )
</script>

<template>
  <h-drawer
    v-model="visible"
    :title="props.faultId ? '编辑故障' : '添加故障'"
    :loading="uploadImgLoading || createLoading || getFaultDetailLoading"
    :width="800"
    unit="px"
  >
    <el-form
      ref="formInstance"
      :rules="faultRules"
      :model="form"
      label-position="top"
      inline-message
      class="modal_form_content fault_desc_form"
    >
      <!-- 商品分类 -->
      <el-form-item label="商品分类" prop="goodsTypeVos">
        <el-select
          v-model="selectedGoodTypeIds"
          placeholder="请选择商品分类"
          :loading="getGoodTypeOptionsLoading"
          multiple
          collapse-tags
          collapse-tags-tooltip
          :max-collapse-tags="3"
        >
          <el-option
            v-for="(goodType, goodTypeIndex) in getAllSecondGoodType"
            :key="goodTypeIndex"
            :label="goodType.name"
            :value="goodType.id"
          ></el-option>
        </el-select>
      </el-form-item>

      <!-- 处理类型 -->
      <el-form-item label="处理类型" prop="oneFaultTypeId">
        <el-select
          v-model="form.oneFaultTypeId"
          :loading="getFaultTypesLoading"
          placeholder="请选择处理类型"
        >
          <el-option
            v-for="(faultType, faultTypeIndex) in faultTypes"
            :key="faultTypeIndex"
            :value="faultType.id"
            :label="faultType.name"
          ></el-option>
        </el-select>
      </el-form-item>

      <!-- 分类代码 -->
      <el-form-item label="分类代码" prop="code">
        <el-input
          v-model.trim="form.code"
          placeholder="请填写分类代码"
          clearable
          maxlength="60"
          @input="form.code = form.code.replace(/[\u4e00-\u9fa5]/g, '')"
        />
      </el-form-item>

      <!-- 分类 -->
      <el-form-item label="分类" prop="name">
        <el-input v-model.trim="form.name" placeholder="请输入分类" clearable maxlength="20" />
      </el-form-item>

      <!-- 故障原因编码 -->
      <el-form-item label="故障原因编码">
        <el-input
          v-model.trim="form.faultReasonCode"
          placeholder="请填写故障原因编码"
          maxlength="60"
          @input="form.faultReasonCode = form.faultReasonCode.replace(/[\u4e00-\u9fa5]/g, '')"
        />
      </el-form-item>

      <!-- 详情 -->
      <el-form-item
        v-for="(item, index) in form.faultReasons"
        :key="index"
        :label="`详情${index + 1}`"
        prop="faultReason"
        class="fault-reason"
      >
        <el-input
          v-model.trim="form.faultReasons[index].content"
          placeholder="请输入详情"
          clearable
          maxlength="100"
          show-word-limit
          resize="both"
          type="textarea"
        />
        <el-space :size="0" :spacer="spacer">
          <h-link
            v-if="form.faultReasons.length > 1"
            type="error"
            :height="28"
            @click="onReasonDel(index)"
            >删除</h-link
          >
          <h-link
            v-if="index === 0 && form.faultReasons.length < 20"
            :height="28"
            @click="onReasonAdd"
            >添加</h-link
          >
        </el-space>
      </el-form-item>

      <!-- 故障图片 -->
      <el-form-item label="故障图片" class="form-item">
        <div style="display: flex; align-items: center; gap: 5px; flex-wrap: wrap">
          <template v-for="(img, imgIndex) in faultImg" :key="imgIndex">
            <h-image
              :src="img.imgUrl"
              :width="60"
              :height="37.5"
              :padding="2"
              :mask-btn-gap="3"
              :initial-index="imgIndex"
              :preview-src-list="faultImg.map((item) => item.imgUrl)"
              @del="handleRemoveImg(img, 'fault')"
            />
          </template>
          <h-image
            v-if="faultImg.length < 10"
            :width="60"
            :height="37.5"
            :padding="2"
            :src="defaultUploadImg"
          >
            <el-upload
              action="#"
              multiple
              accept="image/*"
              :on-change="(file: UploadFile) => handleUploadImg(file, 'fault')"
              :auto-upload="false"
              :show-file-list="false"
            >
              <i class="iconfont icon-img-upload" style="color: #fff; font-size: 24px"></i>
            </el-upload>
          </h-image>
        </div>
      </el-form-item>

      <!-- 维修措施编码 -->
      <el-form-item label="维修措施编码">
        <el-input
          v-model.trim="form.solutionCode"
          placeholder="请填写维修措施编码"
          maxlength="60"
          @input="form.solutionCode = form.solutionCode.replace(/[^0-9a-zA-Z]/g, '')"
        />
      </el-form-item>

      <!-- 维修措施 -->
      <el-form-item
        v-for="(item, index) in form.solutions"
        :key="index"
        :label="`维修措施${index + 1}`"
        class="form-item solve-wrapper"
        prop="solution"
      >
        <el-input
          v-model.trim="form.solutions[index].content"
          placeholder="请输入维修措施"
          clearable
          maxlength="100"
          show-word-limit
          resize="both"
          type="textarea"
        />
        <el-space :size="0" :spacer="spacer">
          <h-link
            v-if="form.solutions.length > 1"
            type="error"
            :height="28"
            @click="onSolveDel(index)"
            >删除</h-link
          >
          <h-link v-if="index === 0 && form.solutions.length < 20" :height="28" @click="onSolveAdd"
            >添加</h-link
          >
        </el-space>
      </el-form-item>

      <!-- 维修建议图片 -->
      <el-form-item label="维修建议图片" class="form-item">
        <div style="display: flex; align-items: center; gap: 5px; flex-wrap: wrap">
          <template v-for="(img, imgIndex) in solveImg" :key="imgIndex">
            <h-image
              :src="img.imgUrl"
              :width="60"
              :height="37.5"
              :padding="2"
              :initial-index="imgIndex"
              :mask-btn-gap="3"
              :preview-src-list="solveImg.map((item) => item.imgUrl)"
              @del="handleRemoveImg(img, 'solve')"
            />
          </template>
          <h-image
            v-if="solveImg.length < 10"
            :width="60"
            :height="37.5"
            :padding="2"
            :src="defaultUploadImg"
          >
            <el-upload
              action="#"
              multiple
              accept="image/*"
              :on-change="(file: UploadFile) => handleUploadImg(file, 'solve')"
              :auto-upload="false"
              :show-file-list="false"
            >
              <i class="iconfont icon-img-upload" style="color: #fff; font-size: 24px"></i>
            </el-upload>
          </h-image>
        </div>
      </el-form-item>

      <div class="same_line switch-wrapper">
        <!-- 移动端是否显示 -->
        <el-form-item label="移动端是否显示" class="same_line">
          <div class="switch_container">
            <el-switch v-model="form.mobileShow" size="small"></el-switch>
            <span v-if="form.mobileShow">显示</span>
            <span v-else>隐藏</span>
          </div>
        </el-form-item>

        <!-- 是否进行报表分析  隐藏-->
        <!-- <el-form-item label="是否进行报表分析" class="same_line">
          <div class="switch_container">
            <el-switch v-model="faultForm.reportAnalysis" size="small"></el-switch>
            <span v-if="faultForm.reportAnalysis">是</span>
            <span v-else>否</span>
          </div>
        </el-form-item> -->

        <!-- 故障状态 -->
        <el-form-item label="故障状态" class="same_line">
          <div class="switch_container">
            <el-switch
              :model-value="!form.status"
              size="small"
              @change="form.status = !form.status"
            />
            <span v-if="!form.status">启用</span>
            <span v-else>禁用</span>
          </div>
        </el-form-item>
      </div>

      <!-- 可见类型 -->
      <el-form-item label="可见类型" prop="visibilityType">
        <el-select v-model="form.visibilityType" placeholder="请选择可见类型">
          <el-option :value="1" label="全部可见"></el-option>
          <el-option :value="2" label="部门可见"></el-option>
          <el-option :value="3" label="客户可见"></el-option>
        </el-select>
      </el-form-item>
    </el-form>

    <template #footer>
      <HButton is-modal type="primary" @click="onSave">确定</HButton>
      <HButton is-modal @click="hideDrawer">取消</HButton>
    </template>
  </h-drawer>
</template>

<style scoped lang="scss">
  :deep(.el-switch__core) {
    height: 16px !important;
    line-height: 16px !important;
  }

  .fault-reason,
  .solve-wrapper {
    :deep(.el-form-item__content) {
      width: 100%;
      display: grid;
      column-gap: 5px;
      grid-template-columns: 1fr minmax(28px, 66px);

      .el-textarea {
        .el-textarea__inner {
          width: 100% !important;
          height: 28px;
          min-height: 28px !important;
          max-height: 85px !important;
        }
      }
    }
  }
</style>
